package com.yifushidai.task;

import com.yifushidai.entity.ApiUniqueMac;
import com.yifushidai.entity.OptDeviceLog;
import com.yifushidai.mapper.*;
import com.yifushidai.service.PowerService;
import com.yifushidai.utils.IpUtil;
import com.yifushidai.utils.ShisuMinaPushUtils;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;

@Component
public class AsyncTask {
    private Logger logger = LoggerFactory.getLogger(AsyncTask.class);
    private static ConcurrentHashMap<String, Thread> powerControlThreadConcurrentHashMap = new ConcurrentHashMap<String, Thread>();//线程安全  插拔卡线程
    private static ConcurrentHashMap<String, Thread> tempKeyThreadConcurrentHashMap = new ConcurrentHashMap<String, Thread>();//线程安全  临时密码线程

    @Autowired
    private PowerService powerService;
    @Autowired
    private OptDeviceLogMapper optDeviceLogMapper;

    @Async("threadPoolTaskExecutor")
    public void nowPushPowerOn(ApiUniqueMac one, String remoteAddressAndSocket) {
        StringBuilder param = new StringBuilder();
        param.append("插卡取电 ");
        // TODO 可以被取消的异步任务(延时线程)
        if (powerControlThreadConcurrentHashMap.get(one.getMac()) != null && !Thread.currentThread().equals(powerControlThreadConcurrentHashMap.get(one.getMac()))) {
            powerControlThreadConcurrentHashMap.get(one.getMac()).interrupt();//两种情况被中断：1.线程正在sleep 2.线程正在循环发送断电指令
        }
        powerControlThreadConcurrentHashMap.put(one.getMac(), Thread.currentThread());

        try {
            Object res = ShisuMinaPushUtils.push(one.getPowerMac(), "powerControl:on");//隔10s发送取电指令，直到收到转发成功标记为止
            if ("OK".equals(res)) {
                powerService.savePower("插卡", "on", one, remoteAddressAndSocket);
            } else {
                optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(remoteAddressAndSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).powerMac(one.getPowerMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务失败").toString()).build());
            }
        } catch (Exception e) {
            optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(remoteAddressAndSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).powerMac(one.getPowerMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务异常").append(e).toString()).build());
        }
    }

    @Async("threadPoolTaskExecutor")
    public void delayPushPowerOf(ApiUniqueMac one, String remoteAddressAndSocket) {
        StringBuilder param = new StringBuilder();
        param.append("拔卡断电 ");
        // TODO 可以被取消的异步任务(延时线程)
        if (powerControlThreadConcurrentHashMap.get(one.getMac()) != null && !Thread.currentThread().equals(powerControlThreadConcurrentHashMap.get(one.getMac()))) {
            powerControlThreadConcurrentHashMap.get(one.getMac()).interrupt();//两种情况被中断：1.线程正在sleep 2.线程正在循环发送断电指令
        }
        powerControlThreadConcurrentHashMap.put(one.getMac(), Thread.currentThread());

        try {
            optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(remoteAddressAndSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).powerMac(one.getPowerMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务延时").append(one.getPowerOfDelay()).append("分钟后执行").toString()).build());
            Thread.sleep(one.getPowerOfDelay() * 60 * 1000);//延时
            Object res = ShisuMinaPushUtils.push(one.getPowerMac(), "powerControl:of");//隔10s发送断电指令，直到收到转发成功标记为止
            if ("OK".equals(res)) {
                powerService.savePower("拔卡", "of", one, remoteAddressAndSocket);
            } else {
                optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(remoteAddressAndSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).powerMac(one.getPowerMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务失败").toString()).build());
            }
        } catch (Exception e) {
            optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(remoteAddressAndSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).powerMac(one.getPowerMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务异常").append(e).toString()).build());
        }
    }

    @Async("threadPoolTaskExecutor")
    public void lockOpenPushTempKey(ApiUniqueMac one, String temp, IoSession ioSession, String remoteAddressAndSocket) {
        StringBuilder param = new StringBuilder();
        param.append("开门推送临时密码").append(temp).append(" ");
        // TODO 可以被取消的异步任务(开门不取消延时推送临时密码)

        try {
            Object res = ShisuMinaPushUtils.push(one.getMac(), "tempKey:" + temp);
            if ("OK".equals(res)) {
                optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(remoteAddressAndSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务成功").toString()).build());
            } else {
                optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(remoteAddressAndSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务失败").toString()).build());
            }
        } catch (Exception e) {
            optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(remoteAddressAndSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务异常").append(e).toString()).build());
        }
    }

    @Async("threadPoolTaskExecutor")
    public void delayPushTempKey(ApiUniqueMac one, long delay, HttpServletRequest request) throws ParseException {
        StringBuilder param = new StringBuilder();
        param.append("延时推送临时密码xxxx ");
        String addressSocket = IpUtil.getIpAddress(request);
        // TODO 可以被取消的异步任务(延时线程)
        if (tempKeyThreadConcurrentHashMap.get(one.getMac()) != null && !Thread.currentThread().equals(tempKeyThreadConcurrentHashMap.get(one.getMac()))) {
            tempKeyThreadConcurrentHashMap.get(one.getMac()).interrupt();//两种情况被中断：1.线程正在sleep 2.线程正在循环发送断电指令
        }
        tempKeyThreadConcurrentHashMap.put(one.getMac(), Thread.currentThread());

        try {
            optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(addressSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务延时").append(delay / 1000).append("秒后执行").toString()).build());
            Thread.sleep(delay);//延时
            Object res = ShisuMinaPushUtils.push(one.getMac(), "tempKey:xxxx");
            if ("OK".equals(res)) {
                optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(addressSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务成功").toString()).build());
            } else {
                optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(addressSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务失败").toString()).build());
            }
        } catch (Exception e) {
            optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(addressSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务异常").append(e).toString()).build());
        }
    }

    @Async("threadPoolTaskExecutor")
    public Future<String> nowPushTempKey(ApiUniqueMac one, String temp, HttpServletRequest request) {
        StringBuilder param = new StringBuilder();
        param.append("即时推送临时密码").append(temp).append(" ");
        String addressSocket = IpUtil.getIpAddress(request);
        // TODO 可以被取消的异步任务(延时线程)
        if (tempKeyThreadConcurrentHashMap.get(one.getMac()) != null && !Thread.currentThread().equals(tempKeyThreadConcurrentHashMap.get(one.getMac()))) {
            tempKeyThreadConcurrentHashMap.get(one.getMac()).interrupt();//两种情况被中断：1.线程正在sleep 2.线程正在循环发送断电指令
        }
        tempKeyThreadConcurrentHashMap.put(one.getMac(), Thread.currentThread());

        Object res = null;
        try {
            res = ShisuMinaPushUtils.push(one.getMac(), "tempKey:" + temp);
            if ("OK".equals(res)) {
                optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(addressSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务成功").toString()).build());
            } else {
                optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(addressSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务失败").toString()).build());
            }
        } catch (Exception e) {
            optDeviceLogMapper.insertSelective(OptDeviceLog.builder().addressSocket(addressSocket).mobile(one.getMobile()).uniqueMac(one.getMac()).alias(one.getAddr() + one.getAlias()).optDesc(param.append("任务异常").append(e).toString()).build());
        }
        return new AsyncResult<>((String) res);
    }
}